//
// Created by HP on 2022/1/4.
//

#ifndef VULKAN_TUTORIAL_LVE_PIPELINE_H
#define VULKAN_TUTORIAL_LVE_PIPELINE_H

#include "lve_device.h"

// std
#include <string>
#include <vector>

namespace lve {

    struct PipelineConfigInfo {
        PipelineConfigInfo(const PipelineConfigInfo&) = delete;
        PipelineConfigInfo& operator=(const PipelineConfigInfo&) = delete;

        VkPipelineViewportStateCreateInfo      viewportInfo;
        VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
        VkPipelineRasterizationStateCreateInfo rasterizationInfo;
        VkPipelineMultisampleStateCreateInfo   multisampleInfo;
        VkPipelineColorBlendAttachmentState    colorBlendAttachment;
        VkPipelineColorBlendStateCreateInfo    colorBlendInfo;
        VkPipelineDepthStencilStateCreateInfo  depthStencilInfo;
        std::vector<VkDynamicState>            dynamicStateEnables;
        VkPipelineDynamicStateCreateInfo       dynamicStateInfo;
        VkPipelineLayout pipelineLayout = nullptr;
        VkRenderPass renderPass = nullptr;
        uint32_t subpass = 0;
    };

    class LvePipeline {
    public:
        LvePipeline(
                LveDevice& device,
                const std::string& vertFilepath,
                const std::string& fragFilepath,
                const PipelineConfigInfo& configInfo);

        ~LvePipeline();

        // 删除赋值构造函数和赋值运算符, 防止意外的复制
        LvePipeline(const LvePipeline&) = delete;
        LvePipeline& operator=(const LvePipeline&) = delete;

        void bind(VkCommandBuffer commandBuffer);
        static void defaultPipelineConfig(PipelineConfigInfo& configInfo);

    private:
        static std::vector<char> readFile(const std::string& filepath);

        void createGraphicPipeline(
            const std::string& vertFilepath,
            const std::string& fragFilepath,
            const PipelineConfigInfo& configInfo);

        void createShaderModule(const std::vector<char>& code, VkShaderModule *shaderModule);

        LveDevice& lveDevice;
        VkPipeline graphPipeline;
        VkShaderModule vertShaderModule;
        VkShaderModule fragShaderModule;
    };
}

#endif //VULKAN_TUTORIAL_LVE_PIPELINE_H
